<?php
/**
 * Copyright (c) 2006-2008, Julien PORTALIER
 * http://featherphp.googlecode.com/
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 */

/**
 * Manages ActiveRecord's validation errors.
 */
class ActiveRecord_Errors implements Iterator
{
	public    $errors = array();
	protected $model;
	
	function __construct(Object $model)
	{
		$this->model = $model;
	}
	
	/**
	 * Adds an error.
	 * 
	 * @param $field String
	 * @param $mesg  String[optional]
	 */
	function add($field, $mesg=null)
	{
		if (!isset($this->errors[$field])) {
			$this->errors[$field] = array();
		}
		$this->errors[$field][] = $mesg;
	}
	
	/**
	 * Checks if field matches given pattern, then adds error (unless there's no error).
	 * 
	 * \code
	 * $this->_errors('name', Valid::NotEmpty, t('Your name is required.'));
	 * $this->_errors('name', Valid::NotBlank, t("Your name can't be blank."));
	 * \endcode
	 * 
	 * @return Boolean Returns false on error; null if field is missing and true otherwise.
	 * @param $field Object
	 * @param $check Object
	 * @param $mesg Object[optional]
	 */
	function test($field, $check, $mesg=null)
	{
		if (isset($this->model->$field))
		{
			if (!preg_match($check, $this->model->$field))
			{
				$this->add($field, $mesg);
				return false;
			}
			return true;
		}
		return null;
	}
	
	/**
	 * Checks if field doesn't matches given pattern, then adds error (unless there's no error).
	 * 
	 * @return Boolean Returns false on error; null if field is missing and true otherwise.
	 * @param $field Object
	 * @param $check Object
	 * @param $mesg Object[optional]
	 */
	function rtest($field, $check, $mesg=null)
	{
		if (isset($this->model->$field))
		{
			if (preg_match($check, $this->model->$field))
			{
				$this->add($field, $mesg);
				return false;
			}
			return true;
		}
		return null;
	}
	
	/**
	 * Returns the total number of errors that have been added.
	 */
	function count()
	{
		return count($this->errors);
	}
	
	/**
	 * Returns true if no errors have been added.
	 */
	function is_empty()
	{
		return empty($this->errors);
	}
	
	/**
	 * Removes all errors that have been added.
	 */
	function clear()
	{
		$this->errors = array();
	}
	
	
	/**
	 * Returns null if field has no error.
	 * Returns a message if fields has one error.
	 * Returns an array of messages if fields has more than one error.
	 * 
	 * @return Mixed
	 * @param $field String
	 */
	function on($field)
	{
		if (!empty($this->errors[$field]))
		{
			return (count($this->errors) > 1) ?
				$this->errors[$field] : $this->errors[$field][0];
		}
		return null;
	}
	
	/**
	 * Returns true if field has no error, false otherwise.
	 * 
	 * @return Boolean
	 * @param $field String
	 */
	function is_valid($field)
	{
		return empty($this->errors[$field]);
	}
	
	
	/**
	 * Exports errors to an XML string.
	 * 
	 * @return String XML
	 */
	function to_xml()
	{
		Load::libs('xml');
		return xml::transform(&$this->errors, 'errors');
	}
	
	/**
	 * Exports errors to a JSON string.
	 * 
	 * @return String JSON
	 */
	function to_json()
	{
		return json_encode($this->errors);
	}
	
	
	// Iterator
	
	function rewind()  { reset($this->errors); }
	function current() { return current($this->errors); }
	function key()     { return key($this->errors); }
	function next()    { return next($this->errors); }
	function valid()   { return (false !== current($this->errors)); }
}
?>